package slices

import (
	"cmp"
	"iter"
	"slices"
)

// 获取切片中给定索引处的元素
func Get[S ~[]E, E any](s S, i int) *E {
	if i >= 0 {
		return &s[i]
	}
	return &s[len(s)-1]
}

// 如果元素不存在添加元素
func UniqAdd[S ~[]E, E comparable](s S, values ...E) []E {
	for _, v := range values {
		if slices.Contains(s, v) {
			continue
		}
		s = append(s, v)
	}
	return s
}

// 去重
func Nodup[S ~[]E, E comparable](s S) []E {
	output := []E{}
	for _, v := range s {
		if slices.Contains(output, v) {
			continue
		}
		output = append(output, v)
	}
	return output
}

// 使用自定义比较器去重
func NodupFunc[S ~[]E, E any](s S, key func(E) string) []E {
	output := []E{}
	keys := []string{}
	for _, v := range s {
		k := key(v)
		if slices.Contains(keys, k){
			continue
		}
		output = append(output, v)
        keys = append(keys, k)
	}
	return output
}

// 比较两个切片
func Equal[S ~[]E, E comparable](s1, s2 S) bool {
	return slices.Equal(s1, s2)
}

func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int {
	return slices.Compare(s1, s2)
}

func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int {
	return slices.CompareFunc(s1, s2, cmp)
}

// 使用自定义比较器比较两个切片
func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool {
	return slices.EqualFunc(s1, s2, eq)
}

// 查找元素索引
func Index[S ~[]E, E comparable](s S, v E) int {
	return slices.Index(s, v)
}

// 使用自定义策略查找元素索引
func IndexFunc[S ~[]E, E any](s S, predicate func(E) bool) int {
	return slices.IndexFunc(s, predicate)
}

// 反向查找元素索引
func LastIndex[S ~[]E, E comparable](s S, v E) int {
	i := len(s) - 1
	for i >= 0 && s[i] != v {
		i--
	}
	return i
}

// 使用给定的断言反向查找元素索引
func LastIndexFunc[S ~[]E, E any](s S, predicate func(E) bool) int {
	for i := len(s) - 1; i >= 0; i-- {
		if predicate(s[i]) {
			return i
		}
	}
	return -1
}

// 获取第一个元素
func First[S ~[]E, E any](s S) *E {
	if len(s) == 0 {
		return nil
	}
	return &s[0]
}

// 获取最后一个元素
func Last[S ~[]E, E any](s S) *E {
	if len(s) == 0 {
		return nil
	}
	return &s[len(s)-1]
}

// 在切片中查找符合条件的元素
func Find[S ~[]E, E comparable](s S, predicate func(E) bool) *E {
	for i := range s {
		if predicate(s[i]) {
			return &s[i]
		}
	}
	return nil
}

func Contains[S ~[]E, E comparable](s S, values ...E) bool {
	for _, v := range values {
		if !slices.Contains(s, v) {
			return false
		}
	}
	return true
}

func ContainsAny[S ~[]E, E comparable](s S, values ...E) bool {
	for _, v := range values {
		if slices.Contains(s, v) {
			return true
		}
	}
	return false
}

func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
	return IndexFunc(s, f) >= 0
}

// 判断切片中是否所有元素都满足给定条件
func AllMatch[S ~[]E, E any](s S, predicate func(E) bool) bool {
	for _, v := range s {
		if !predicate(v) {
			return false
		}
	}
	return true
}

// 判断切片中是否存在任意元素满足给定条件
func AnyMatch[S ~[]E, E any](s S, predicate func(E) bool) bool {
	for _, v := range s {
		if predicate(v) {
			return true
		}
	}
	return false
}

func Insert[S ~[]E, E any](s S, i int, v ...E) S {
	return slices.Insert(s, i, v...)
}

// 删除从i到j的元素
func Delete[S ~[]E, E any](s S, i, j int) S {
	return slices.Delete(s, i, j)
}

// 删除满足给定条件的元素
func DeleteFunc[S ~[]E, E any](s S, predicate func(E) bool) S {
	return slices.DeleteFunc(s, predicate)
}

// 移除元素
func Remove[S ~[]E, E comparable](s S, item E) S {
	return slices.DeleteFunc(s, func(el E) bool {
		return item == el
	})
}

func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
	return slices.Replace(s, i, j, v...)
}

func Clone[S ~[]E, E any](s S) S {
	return append(s[:0:0], s...)
}

func Compact[S ~[]E, E comparable](s S) S {
	return slices.Compact(s)
}

func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
	return slices.CompactFunc(s, eq)
}

func Grow[S ~[]E, E any](s S, n int) S {
	return slices.Grow(s, n)
}

// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
func Clip[S ~[]E, E any](s S) S {
	return s[:len(s):len(s)]
}

// Reverse reverses the elements of the slice in place.
func Reverse[S ~[]E, E any](s S) {
	slices.Reverse(s)
}

// Concat returns a new slice concatenating the passed in slices.
func Concat[S ~[]E, E any](slice ...S) S {
	return slices.Concat(slice...)
}

func Repeat[S ~[]E, E any](x S, count int) S {
	return slices.Repeat(x, count)
}

// 分组转换为map. GroupBy groups elements of the slice into a map by keySelector
func GroupBy[S ~[]E, E any](s S, keySelector func(E) string) map[string][]E {
	result := make(map[string][]E)
	for _, item := range s {
		key := keySelector(item)
		result[key] = append(result[key], item)
	}
	return result
}

// 转换为字符串切片
func MapString[S ~[]E, E any](s S, mapper func(int, E) string) []string {
	result := make([]string, len(s))
	for i, item := range s {
		result[i] = mapper(i, item)
	}
	return result
}

// 切片映射转换为指定类型的切片
func Map[S ~[]E, E any, R any](s S, mapper func(int, E) R) []R {
	result := make([]R, len(s))
	for i, item := range s {
		result[i] = mapper(i, item)
	}
	return result
}

// 切片过滤，Filter a slice using the predicate
func Filter[S ~[]E, E any](s S, predicate func(E) bool) []E {
	var result []E
	for _, item := range s {
		if predicate(item) {
			result = append(result, item)
		}
	}
	return result
}

func All[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] {
	return slices.All(s)
}

func Backward[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] {
	return slices.Backward(s)
}

func Values[Slice ~[]E, E any](s Slice) iter.Seq[E] {
	return slices.Values(s)
}

func AppendSeq[Slice ~[]E, E any](s Slice, seq iter.Seq[E]) Slice {
	return slices.AppendSeq(s, seq)
}

func Collect[E any](seq iter.Seq[E]) []E {
	return slices.Collect(seq)
}

func Sorted[E cmp.Ordered](seq iter.Seq[E]) []E {
	return slices.Sorted(seq)
}

func SortedFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
	return slices.SortedFunc(seq, cmp)
}

func SortedStableFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
	return slices.SortedStableFunc(seq, cmp)
}

func Chunk[Slice ~[]E, E any](s Slice, n int) iter.Seq[Slice] {
	return slices.Chunk(s, n)
}
